<?php
/**
 * GioCMS
 * 
 * LICENSE
 *
 * This source file is subject to the GNU GENERAL PUBLIC LICENSE Version 2 
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-2.0.txt
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@ninhgio.com so we can send you a copy immediately.
 * 
 * @copyright	Copyright (c) 2010-2011 GioCMS (http://cms.ninhgio.com)
 * @license		http://www.gnu.org/licenses/gpl-2.0.txt GNU GENERAL PUBLIC LICENSE Version 2
 * @author		NinhGio - ninhgio@gmail.com
 * @since		1.0
 */

class Modules_Core_Services_User
{
	public static function validate($userData)
	{
		$validator = new Gio_Core_Validator();
		foreach ($userData as $index => $value) {
			if (gettype($value) == 'string') {
				$userData[$index] = trim($value);
			}
		} 
		$userData['messages']['username'] = $validator->setString($userData['username'])
												->validate(array('notNull', 'isUsername')
																, array(
																	'notNull' => 'user_username_notnull',
																	'isUsername' => 'user_username_invalid'
																)
														);
		$userData['messages']['password'] = $validator->setString($userData['password'])
												->validate(array('notNull'), array('notNull' => 'user_password_notnull'));
		$userData['messages']['password_confirm'] = $validator->setString($userData['password_confirm'])
														->validate(array('notNull', 'compare' => array($userData['password']))
																	, array(
																		'notNull' => 'user_password_confirm_notnull',
																		'compare' => 'user_password_confirm_not_match'
																	)
																);
		$userData['messages']['email'] = $validator->setString($userData['email'])
												->validate(array('notNull', 'isEmail')
																, array(
																	'notNull' => 'user_email_notnull',
																	'isEmail' => 'user_email_invalid'
																)
														);
												
		$userData['messages']['fullname'] = $validator->setString($userData['fullname'])
												->validate(array('notNull'), array('notNull' => 'user_fullname_notnull'));

		$error = false;
		foreach ($userData['messages'] as $index => $message) {
			if ($message) {
				$userData['messages_error'] = true;
				return $userData;
			}
		}										
		$userData['messages_error'] = false;
		return $userData; 
	}
	
	public static function validatePassword($data)
	{
		$validator = new Gio_Core_Validator();
		foreach ($data as $index => $value) {
			if (gettype($value) == 'string') {
				$data[$index] = trim($value);
			}
		}
		
		$data['messages']['oldpassword'] = $validator->setString($data['oldpassword'])
														->validate(array('notNull', 'compare' => array($data['password']))
																	, array(
																		'notNull' => 'user_changepassword_oldpassword_notnull',
																		'compare' => 'user_changepassword_oldpassword_not_match'
																	)
																);
		
		$data['messages']['newpassword'] = $validator->setString($data['newpassword'])
														->validate(array('notNull')
																	, array(
																		'notNull' => 'user_changepassword_newpassword_notnull',
																	)
																);
																
		$data['messages']['newpassword_confirm'] = $validator->setString($data['newpassword_confirm'])
														->validate(array('notNull', 'compare' => array($data['newpassword']))
																	, array(
																		'notNull' => 'user_changepassword_newpassword_confirm_notnull',
																		'compare' => 'user_changepassword_newpassword_confirm_not_match'
																	)
																);
		
		$error = false;
		foreach ($data['messages'] as $index => $message) {
			if ($message) {
				$data['messages_error'] = true;
				return $data;
			}
		}										
		$data['messages_error'] = false;
		return $data;
	}
	
	public static function getById($id)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->getById($id);
	}
	
	public static function getByUsername($username, $userId = null)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->getByUsername($username, $userId);
	}
	
	public static function getByEmail($email, $userId = null)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->getByEmail($email, $userId);
	}
	
	public static function getByOpenID($url)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->getByOpenID($url);
	}
	
	public static function add($user)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->add($user);
	}
	
	public static function auth($username, $password, $adminSection = true)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->auth($username, $password, $adminSection);
	}
	
	public static function changepassword($user)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->changepassword($user);
	}
	
	public static function find($condition = array(), $offset = null, $limit = null)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->find($condition, $offset, $limit);
	}
	
	public static function count($condition = array())
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->count($condition);
	}
	
	public static function update($user)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->update($user);
	}
	
	public static function updatePasswordFor($username, $password)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->updatePasswordFor($username, $password);
	}
	
	public static function setLastLogin($user)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$userDao = new Modules_Core_Models_Mysql_User();
		$userDao->setConnection($conn);
		return $userDao->setLastLogin($user);
	}
	
	public static function checkEmailExist($email)
	{
		$conn		= Gio_Db_Connection::getConnection();
		$dao = new Modules_Core_Models_Mysql_User();
		$dao->setConnection($conn);
		return $dao->getByEmail($email);
	}
	
	/**
	 * Generate random password
	 * 
	 * @return string
	 */
	public static function generatePassword()
	{
		return substr(md5(rand(100000, 999999)), 0, 8);
	}
	
	/**
	 * Encrypt user's password
	 * 
	 * @param string $password
	 * @param string $salt
	 * @return string
	 */
	public static function encryptPassword($password, $salt)
	{
		return md5(md5($password) . $salt);
	}
	
	/**
	 * Provide the link (via email) for user to reset the password
	 * 
	 * @param string $username
	 * @param string $email
	 * @return bool Returns false if user is not found or can not send email, 
	 * true otherwise
	 */
	public static function sendPassword($username, $email, $code)
	{
		$criteria = array('username' => $username, 'email' => $email);
		$users    = self::find($criteria, null, null);
		
		if ($users == null || count($users) == 0) {
			return false;
		}
		
		/**
		 * Send the confirmation link to reset password via email 
		 */
		$user     = $users[0];
		$template = Modules_Mail_Services_Template::getByName(Modules_Mail_Models_Template::TEMPLATE_FORGOT_PASSWORD);
		if ($template == null) {
			throw new Exception('MAIL_TEMPLATE_NOT_FOUND');
		}
		
		$search  	 = array(Modules_Mail_Models_Mail::MAIL_VARIABLE_EMAIL, Modules_Mail_Models_Mail::MAIL_VARIABLE_USERNAME);
		$replace 	 = array($user['email'], $user['username']);
		$subject 	 = str_replace($search, $replace, $template['subject']);
		$content 	 = str_replace($search, $replace, $template['body']);
		
		/**
		 * Replace the reset password link
		 * @TODO: Add security key?
		 */
		$view = Gio_Core_View::getInstance();
		$json = new Services_JSON();
		$encodedLink = array(
			'username' 		=> $username,
			'email'     	=> $email,
			'code'			=> $code,
		);
		$encodedLink = base64_encode(urlencode($json->encodeUnsafe($encodedLink)));
		$link    	 = $view->url('core_user_resetpassword', array('encoded_link' => $encodedLink));
		$content 	 = str_replace('%reset_link%', $link, $content);
		/**
	 	 * Get mail transport instance
	 	 */
		$mailer   = Modules_Mail_Services_Mailer::getMailTransport();
		$mailer->From 		= $template['from_mail'];
		$mailer->FromName 	= $template['from_name'];
		$mailer->AddAddress($user['email'], $user['username']);
		$mailer->AddReplyTo($template['reply_to_mail'], $template['reply_to_name']);	
		$mailer->WordWrap = 50; // set word wrap
		$mailer->IsHTML(true); // send as HTML
		$mailer->Subject = $subject;
		$mailer->Body = $content; //HTML Body
		$mailer->AltBody = ""; //Text Body
						
		if(!$mailer->Send()) {
			return false;
		} else {
			return true;
		}	 
	}
	
	/**
	 * Reset the user's password
	 * 
	 * @param string $link The encoded link
	 * @return bool
	 */
	public static function resetPassword($link)
	{
		$json = new Services_JSON();
		$criteria = (array)$json->decode(urldecode(base64_decode($link)));
		
		if (!isset($criteria['username']) || null == $criteria['username']
			|| !isset($criteria['email']) || null == $criteria['email']
			|| !isset($criteria['code']) || null == $criteria['code'])
		{
			return false;
		}
		$users    = Modules_Core_Services_User::find($criteria, null, null);
		if ($users == null || count($users) == 0) {
			return false;
		}
		/**
	 	 * Send the confirmation link to reset password via email 
	 	 */
		$user     = $users[0];
						
		/**
		 * Reset the password
		 */
		$password = self::generatePassword();
		
		$passwordEncrypt = self::encryptPassword($password, $user['salt']);
		self::updatePasswordFor($user['username'], $passwordEncrypt);
		
		$template = Modules_Mail_Services_Template::getByName(Modules_Mail_Models_Template::TEMPLATE_NEW_PASSWORD);
		if ($template == null) {
			return;
		}
		
		$view = Gio_Core_View::getInstance();
		$search  	 = array(Modules_Mail_Models_Mail::MAIL_VARIABLE_EMAIL, Modules_Mail_Models_Mail::MAIL_VARIABLE_USERNAME);
		$replace 	 = array($user['email'], $user['username']);
		$subject 	 = str_replace($search, $replace, $template['subject']);
		$content 	 = str_replace($search, $replace, $template['body']);
		$content   	 = str_replace('%new_password%', $password, $content);
		$content   	 = str_replace('%link%', $view->url('core_auth_login'), $content);
		/**
	 	 * Get mail transport instance
	 	 */
		$mailer   = Modules_Mail_Services_Mailer::getMailTransport();
		$mailer->From 		= $template['from_mail'];
		$mailer->FromName 	= $template['from_name'];
		$mailer->AddAddress($user['email'], $user['username']);
		$mailer->AddReplyTo($template['reply_to_mail'], $template['reply_to_name']);	
		$mailer->WordWrap = 50; // set word wrap
		$mailer->IsHTML(true); // send as HTML
		$mailer->Subject = $subject;
		$mailer->Body = $content; //HTML Body
		$mailer->AltBody = ""; //Text Body
						
		if(!$mailer->Send()) {
			return false;
		} else {
			return true;
		}
	}
	
	/**
	 * Provide the link (via email) for user to reset the password
	 * 
	 * @param string $username
	 * @param string $email
	 * @return bool Returns false if user is not found or can not send email, 
	 * true otherwise
	 */
	public static function registerSuccess($username, $email)
	{
		$criteria = array('username' => $username, 'email' => $email);
		$users    = self::find($criteria, null, null);
		
		if ($users == null || count($users) == 0) {
			return false;
		}
		
		/**
		 * Send the confirmation link to reset password via email 
		 */
		$user     = $users[0];
		$template = Modules_Mail_Services_Template::getByName(Modules_Mail_Models_Template::TEMPLATE_REGISTER_SUCCESS);
		if ($template == null) {
			return;
			//throw new Exception('MAIL_TEMPLATE_NOT_FOUND');
		}
		
		$search  	 = array(Modules_Mail_Models_Mail::MAIL_VARIABLE_EMAIL, Modules_Mail_Models_Mail::MAIL_VARIABLE_USERNAME);
		$replace 	 = array($user['email'], $user['username']);
		$subject 	 = str_replace($search, $replace, $template['subject']);
		$content 	 = str_replace($search, $replace, $template['body']);
		
		/**
	 	 * Get mail transport instance
	 	 */
		$mailer   = Modules_Mail_Services_Mailer::getMailTransport();
		$mailer->From 		= $template['from_mail'];
		$mailer->FromName 	= $template['from_name'];
		$mailer->AddAddress($user['email'], $user['username']);
		$mailer->AddReplyTo($template['reply_to_mail'], $template['reply_to_name']);	
		$mailer->WordWrap = 50; // set word wrap
		$mailer->IsHTML(true); // send as HTML
		$mailer->Subject = $subject;
		$mailer->Body = $content; //HTML Body
		$mailer->AltBody = ""; //Text Body
						
		if(!$mailer->Send()) {
			return false;
		} else {
			return true;
		}	 
	}
}